﻿// /********************************************************************
// *创建日期:2019年11月04日 16:29
// * 文件名:KPluginDemoService.SqlRes.cs
// *作者:  ghui
// *说明: 后台脚本开发案例
// 
// 
// 
//  *********************************************************************/

using System;
using System.Collections.Generic;
using System.Data;
using Demo.Contract.Entitiy;
using KPFramework.Base;
using KPFramework.Data;
using KPFramework.Data.Entity;
using KPFramework.Extensions;
using KPFramework.Res.Attr;
using KPFramework.Res.ResObject;
using KPFramework.SysService.DBService.Utils;

namespace Demo.Data.Services.DemoService
{
    partial class KPluginDemoService
    {
        #region 增、删、改操作

        /// <summary>
        /// 使用实体作为参数，添加用户对象
        /// (不用创建脚本资源)
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public UserVo AddUserInfo(UserVo userInfo)
        {
            if (userInfo == null)
                return null;
            //数据校验:略
            var sql  = new SqlResObject();
            if (!sql.Insert(userInfo))
            {
                //操作失败:+sqlAdd.LastError;
                return null;
            }
            return userInfo;
        }


        /// <summary>
        /// 添加用户对象
        /// （不创建脚本）
        /// </summary>
        /// <param name="objData"></param>
        /// <returns></returns>
        public UserVo AddUserInfo2(KObject objData)
        {
            if (objData == null)
                return null;
            //数据校验:略
            objData.Name = EntityBase.GetObjectName<UserVo>();//绑定表明
            var sql = new SqlResObject();
            if (!sql.Insert(objData))
            {
                //操作失败:+sqlAdd.LastError;
                return null;
            }
            return objData.GetObject<UserVo>();
        }

        /// <summary>
        /// 添加用户信息(SYSTEMCORE.K_USER_INFO)
        /// 创建脚本资源:SQLAddUserInfo
        /// </summary>
        /// <param name="objData"></param>
        /// <returns></returns>
        public UserVo AddUserInfo(KObject objData)
        {
            if (objData == null)
                return null;
            if (objData.IsNullOrEmpty(Common.ID, Common.NAME))
            {
                //用户Id，用户姓名不能为空
                return null;
            }

            //使用小助手添加资源:SQLAddUserInfo,
            //脚本:INSERT INTO SYSTEMCORE.K_USER_INFO () VALUES()
            var sqlAdd = new SqlResObject("SQLAddUserInfo");

            //验证用户是否已经存在
            string strUserName = objData.GetValueStr(Common.UserName);
            var sql = new SqlResObject(){DBName = sqlAdd.DBName};//使用同一个数据库连接

            KObject objTable = new KObject(){Name = "SYSTEMCORE.K_USER_INFO" };
            //或者
            //KObject objTable = new KObject(){Name =  EntityBase.GetObjectName<UserVo>()};

            objTable.SetValue(Common.UserName, strUserName);
            if (sql.Count(objTable, Cnd.Where(Common.UserName, "=")) > 0)
            {
                //相同用户名已经存在
                return null;
            }
            //添加用户
            if (sqlAdd.GetRes(objData) == null)
            {
                //操作失败:+sqlAdd.LastError;
                return null;
            }

            //返回添加的User对象
            return objData.GetObject<UserVo>();
        }



        /// <summary>
        /// 删除用户根据Id
        /// </summary>
        /// <param name="strId"></param>
        /// <returns></returns>
        public bool DeleteUser(string strId)
        {
            if (strId.IsNullOrEmpty())
                return false;


            //1.使用资源删除,创建资源SQLDeleteUserInfo
            var sql1 = new SqlResObject("SQLDeleteUserInfo");
            KObject objIn = new KObject(new { id = strId });
            if (sql1.GetRes(objIn) == null)
            {
                //操作失败
                return false;
            }

            //2.不使用资源
            var sql2 = new SqlResObject();
            UserVo userVo = new UserVo(){Id = strId};
            if (!sql2.Delete(userVo, Cnd.Where("ID", "=")))
            {
                //操作失败
                return false;
            }

            //3.不使用资源,使用KObject操作
            KObject objPars = new KObject(){Name = "SYSTEMCORE.K_USER_INFO" };
            objPars.SetValue("ID", strId);
            var sql3 = new SqlResObject();
            if (sql3.Delete(objPars, Cnd.Where("ID", "=")))
            {
                //操作失败
                return false;
            }

            return true;
        }


        /// <summary>
        /// 根据Id，更新用户信息
        /// </summary>
        /// <param name="objInfo"></param>
        /// <returns></returns>
        public bool UpdateUser(KObject objInfo)
        {
            if (objInfo == null)
                return false;
            //校验:略
            string strId = objInfo.GetValueStr(Common.ID);

            //1.使用资源删除,创建资源SQLUpdateUserInfo
            var sql1 = new SqlResObject("创建资源SQLUpdateUserInfo");
            KObject objIn = new KObject(new { id = strId });
            if (sql1.GetRes(objIn) == null)
            {
                //操作失败
                return false;
            }

            //2.不使用资源
            var sql2 = new SqlResObject();
            UserVo userVo = objIn.GetObject<UserVo>();
            if (!sql2.Update(userVo, Cnd.Where("ID", "=")))
            {
                //操作失败
                return false;
            }

            //3.不使用资源,使用KObject操作
            objInfo.Name = "SYSTEMCORE.K_USER_INFO";//绑定表名
            var sql3 = new SqlResObject();
            if (sql3.Delete(objInfo, Cnd.Where("ID", "=")))
            {
                //操作失败
                return false;
            }

            return true;
        }
        #endregion

        #region 事物管理功能

        /// <summary>
        /// 添加用户时同时，创建员工信息COMM.StAFF_DICT
        /// 旧的事物操作控制
        /// </summary>
        /// <param name="objInfo"></param>
        /// <returns></returns>
        public bool AddUserTransOld(KObject objInfo)
        {
            if (objInfo == null)
                return false;
            //校验:略

            KObject objUserInfo = objInfo.Clone(false);
            KObject objStaffInfo = objInfo.Clone(false);
            //创建2个资源:SQLAddUserInfo,SQLAddStaffInfo
            var sqlAddUser = new SqlResObject("SQLAddUserInfo");
            var sqlAddStaff = new SqlResObject("SQLAddStaffInfo");

            //开启事物
            string strTransId = sqlAddUser.BeginTrans();
            try
            {
                objUserInfo.SetValue(Common.TransID, strTransId);
                if (sqlAddUser.GetRes(objUserInfo) == null)
                {
                    //操作失败
                    sqlAddUser.RollBackTrans(strTransId);
                    return false;
                }

                objStaffInfo.SetValue(Common.TransID, strTransId);
                if (sqlAddStaff.GetRes(objStaffInfo) == null)
                {
                    //操作失败
                    sqlAddUser.RollBackTrans(strTransId);
                    return false;
                }

                //提交事物
                sqlAddUser.CommitTrans(strTransId);
                return true;
            }
            catch (Exception e)
            {
                sqlAddUser.RollBackTrans(strTransId);
                return false;
            }
        }


        /// <summary>
        /// 添加用户时同时，创建员工信息COMM.StAFF_DICT
        /// 使用SqlResObject对象的生命周期控制
        /// </summary>
        /// <param name="objInfo"></param>
        /// <returns></returns>
        public bool AddUserTransNew(KObject objInfo)
        {
            if (objInfo == null)
                return false;
            //校验:略

            KObject objUserInfo = objInfo.Clone(false);
            KObject objStaffInfo = objInfo.Clone(false);

            //AutoCommit:true,生命周期结束时自动Commit,false:生命周期时Rollback
            using (var sqlAddUser = new SqlResObject("SQLAddUserInfo") {AutoCommit = false})
            {
                try
                {
                    sqlAddUser.BeginTrans();
                    //sqlAddStaff,使用sqlAddUser作为“友好联姻资源"
                    var sqlAddStaff = new SqlResObject("SQLAddStaffInfo", sqlAddUser);

                    if (sqlAddUser.GetRes(objUserInfo) == null)
                    {
                        //操作失败
                        sqlAddUser.RollBackTrans();
                        return false;
                    }

                    if (sqlAddStaff.GetRes(objStaffInfo) == null)
                    {
                        //操作失败
                        sqlAddUser.RollBackTrans();
                        return false;
                    }
                    //提交事物(AutoCommit=true)时，CommitTrans 可忽略
                    sqlAddUser.CommitTrans();
                    return true;
                }
                catch (Exception e)
                {
                    //操作异常
                    sqlAddUser.RollBackTrans();
                    return false;
                }
            }
        }


        /// <summary>
        /// 添加用户时同时，创建员工信息COMM.StAFF_DICT
        /// 使用SqlResObject对象的生命周期控制,改进版
        /// </summary>
        /// <param name="objInfo"></param>
        /// <returns></returns>
        public bool AddUserTransNew2(KObject objInfo)
        {
            if (objInfo == null)
                return false;
            //校验:略

            KObject objUserInfo = objInfo.Clone(false);
            KObject objStaffInfo = objInfo.Clone(false);

            //AutoCommit:true,生命周期结束时自动Commit,false:生命周期时Rollback
            using (var sqlAddUser = new SqlResObject("SQLAddUserInfo") { AutoCommit = false })
            {
                try
                {
                    sqlAddUser.BeginTrans();
                    //sqlAddStaff,使用sqlAddUser作为“友好联姻资源"
                    var sqlAddStaff = new SqlResObject("SQLAddStaffInfo", sqlAddUser);

                    if (sqlAddUser.GetRes(objUserInfo) == null)
                    {
                        //操作失败-(直接抛出异常,catch,回滚事物)
                       throw new Exception(sqlAddUser.LastError);
                    }

                    if (sqlAddStaff.GetRes(objStaffInfo) == null)
                    {
                        //操作失败-(直接抛出异常,catch,回滚事物)
                        throw new Exception(sqlAddUser.LastError);
                    }
                    //提交事物(AutoCommit=true)时，CommitTrans 可忽略
                    sqlAddUser.CommitTrans();
                    return true;
                }
                catch (Exception e)
                {
                    //操作异常
                    sqlAddUser.RollBackTrans();
                    return false;
                }
            }
        }
        #endregion

        #region 常用的聚合查询

        /// <summary>
        /// 汇总，
        /// 同名用户的数量
        /// (COUNT,MIN,MAX,SUM，使用方法相同)
        /// </summary>
        /// <param name="strName"></param>
        /// <returns></returns>
        public int GetUsersSum(string strName)
        {
            //参数
            KObject objPars = new KObject(new {name = strName})
            {
                Name = EntityBase.GetObjectName<UserVo>()
            };

            //1. 使用资源汇总,SQLGetUsersSum,
            //SELECT SUM(*) FROM SYSTEMCORE.K_USER_INFO WHERE NAME = '{NAME}'
            var sqlRes = new SqlResObject("SQLGetUsersSum");
            int nData = 0;
            var value = sqlRes.GetResValue(objPars);
            nData = value.ToString().ToInt32();

            //2. 使用聚合方法,不创建资源
            var sql2 = new SqlResObject();
            nData = sql2.Sum(objPars, "ID", Cnd.Where("NAME", "="));

            return nData;
        }


        /// <summary>
        /// 汇总，
        /// 年龄> nAge 的用户数量
        /// (COUNT,MIN,MAX,SUM，使用方法相同)
        /// </summary>
        /// <param name="nAge"></param>
        /// <returns></returns>
        public int GetUsersSum2(int nAge)
        {
            //参数
            KObject objPars = new KObject(new { age = nAge })
            {
                Name = EntityBase.GetObjectName<UserVo>()
            };

            //1. 使用资源汇总,SQLGetUsersSumByAge,
            //SELECT SUM(*) FROM SYSTEMCORE.K_USER_INFO WHERE AGE > {AGE}
            var sqlRes = new SqlResObject("SQLGetUsersSumByAge");
            int nData = 0;
            var value = sqlRes.GetResValue(objPars);
            nData = value.ToString().ToInt32();

            //2. 使用聚合方法,不创建资源
            var sql2 = new SqlResObject();
            nData = sql2.Sum(objPars, "ID", Cnd.Where("AGE", ">"));

            return nData;
        }


        #endregion

        #region Cnd动态的查询条件

        /// <summary>
        /// Cnd,提供了动态传入查询条件的能力,
        /// 改功能在复杂的脚本中不适合，只用于简单语句
        /// op:=,<>,> ,<,>=,<= 等
        /// 例:查询姓名=strName,或者年龄> nAge的性别为男的用户
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="nAge"></param>
        /// <returns></returns>
        public DataTable GetUserList(string strName, int nAge)
        {
            KObject objPars = new KObject(new
            {
                age = nAge,
                name = strName,
                sex = "男"
            })
            {
                Name = EntityBase.GetObjectName<UserVo>()
            };

            var sql = new SqlResObject();
            DataTable dt = sql.Query(objPars, Cnd.Where("NAME", "=").And("SEX", "=").Or("AGE", ">"));
            //如果返回实体
            List<UserVo> listUser = dt.ToEnties<UserVo>();
            return dt;
        }
        #endregion


        #region 常用查询

        /// <summary>
        /// 获得用户信息（单表)
        /// </summary>
        /// <param name="strId"></param>
        /// <returns></returns>
        public UserVo GetUserInfo(string strId)
        {
            KObject objData = new KObject(new {id = strId});
            //1.使用资源参数,SQLGetUserInfo,
            var sql = new SqlResObject("SQLGetUserInfo");
            KObject objUser = sql.GetResFirst(objData);
            //或者
            objUser = sql.GetResFirst(objData);

            //2. 不使用资源,单表查询
            objData.Name = EntityBase.GetObjectName<UserVo>();//绑定表名
            var sqlRes = new SqlResObject();
            objUser = sqlRes.QueryFirst(objData, Cnd.Where("ID", "="));

            //返回实体对象
            return objUser?.GetObject<UserVo>();
        }

        /// <summary>
        /// 使用配置的资源，查询数据
        /// </summary>
        /// <returns></returns>
        public DataTable GetUserDatasList()
        {
            KObject objPars = new KObject();

            //1.使用Query查询
            var sql = new SqlResObject("资源名称");
            DataTable dt = sql.Query(objPars);
            //或
            dt = sql.Query(new {id = "", name = ""});

            //2.使用GetRes
            dt = sql.GetResDt(objPars);

            //3.旧的写法
            objPars.SetValue(Common.VALUE_TYPE, (int) E_ValueType.VT_DataTable);
            dt = sql.GetRes(objPars) as DataTable;

            return dt;
        }

        #endregion

        #region 强制的实体映射操作功能
        /*系统数据使用Dapper框架，进行实体映射封装,具体可百度Dapper
         *Dapper要求实体映射需 属性 匹配,因此使用时，创建实体要有数据库
         * 表字段对应
         * SqlResObject，GetRes<T>函数组提供了该功能
         */

        internal class UserDapper
        {
            public string Id { get; set; }
            public string Name { get; set; }

            public string user_name { get; set; }

        }


        /// <summary>
        /// 基于Dapper的实体操作
        /// </summary>
        /// <returns></returns>
        public List<UserDapper> DapperResOper()
        {
            KObject objPars = new KObject();
            string strResName = "资源名";
            var  sql = new SqlResObject(strResName);
            //获取数据
            var listUser = sql.GetResDapper<UserDapper>(objPars);
            //或者
            listUser = sql.GetResDapper<UserDapper>(new {par = "参数"});

            var userInfo = sql.GetResFirstDapper<UserDapper>(objPars);

            return listUser;
        }
        #endregion

        #region 分页查询
        /// <summary>
        /// 分页查询,系统默认将参数:
        /// START_ROW,END_ROW,作为参数传递给资源，作为资源的参数,
        /// 需要在脚本中利用参数进行处理.
        /// </summary>
        /// <returns></returns>
        public PageData<UserVo> QueryPage()
        {
            KObject objPars = new KObject();
            string strResName = "资源名";
            var sql = new SqlResObject(strResName);

            int nPageSize = 20;//如果小于0，默认为20
            int nPage = 1;//如果小于0，默认为第一个页

            //默认返回DataTabe
            PageDataNormal dtNormal = sql.QueryPage(nPageSize, nPage, objPars);
            //只返回datarow
            PageData<DataRow> dtRow = sql.Query(nPageSize, nPage, objPars);


            //查询实体
            var data = sql.Query<UserVo>(nPageSize, nPage, objPars);

            return data;
        }
        #endregion 


        #region 运行时脚本资源

        /// <summary>
        /// 资源名称作为注解
        /// </summary>
        /// <param name="strId"></param>
        /// <returns></returns>
        [Res("SQLGetUserInfo")]
        public KObject GetUserInfoRt(string strId)
        {
            return SqlResObject.ExecuteRunTimeFirst(new {id = strId});
        }

        /// <summary>
        /// 使用匿名注解,SQL+方法名作为资源名
        /// 如:SQL+GetUserList,SQLGetUserList
        /// </summary>
        /// <param name="strName"></param>
        /// <returns></returns>
        public DataTable GetUserList(string strName)
        {
            //实际使用的资源为:SQLGetUserList
            DataTable dt = SqlResObject.ExecuteRunTimeDt(new {name = strName});
            return dt;
        }


        /// <summary>
        /// 批量事物注解使用
        /// </summary>
        /// <param name="objUserInfo"></param>
        /// <returns></returns>
        [Res("SQLAddUserInfo")]
        [Res("SQLAddStaffInfo")]
        public bool AddUserRt(KObject objUserInfo)
        {
            KObject objPars = objUserInfo.Clone(false);
            return SqlResObject.ExecuteRunTime2(objPars);
        }

        /// <summary>
        /// 注解的运行时管理
        /// </summary>
        /// <returns></returns>
        [Res("SQLAddUserInfo")]
        [Res("SQLAddStaffInfo")]
        public bool ResRtDemo()
        {
            //获得注解的资源字典
            var resDict = SqlResObject.RDict();
            var addUserInfo = resDict["SQLAddUserInfo"];
            var addStaff = resDict["SQLAddStaffInfo"];

            //获取绑定的注解资源(根据顺序)
            var addUser = SqlResObject.R();//第一个注解资源:SQLAddUserInfo

            return true;
        }
        #endregion 


        #region 其他功能

        /// <summary>
        /// Sql资源的其他使用案例
        /// </summary>
        public void SqlResDemo()
        {
            KObject objPars = new KObject();

            //1.资源的直接创建
            SqlResObject sql = "SQLGetUserInfo";
            var userInfo = sql.GetRes(objPars);

            
        }
        #endregion 
    }
}